# coding = utf-8
import time
from io import BytesIO

from django.db import transaction
from django.db.models import Q
from django.http import HttpResponse
from django.utils.encoding import escape_uri_path
from openpyxl.styles import Border, Side, Alignment
from openpyxl.utils import get_column_letter
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
import pandas as pd

from base.models import Category
from store.api.utils import store_decrease_goods_stocks
from store.models import GoodsStock, GoodsTransferDetail, GoodsTransfer
from .serializers import GoodsStockSerializer, GoodsTransferDetailSerializer, GoodsTransferSerializer


class GoodsStockViewSet(ModelViewSet):
    """商品库存"""
    permission_classes = ()
    queryset = GoodsStock.objects.all()
    serializer_class = GoodsStockSerializer

    def get_queryset(self):
        queryset = super().get_queryset()

        goods_id = self.request.query_params.get("goods_id", None)
        code = self.request.query_params.get("code", None)
        name = self.request.query_params.get("name", None)
        help_code = self.request.query_params.get("help_code", None)
        bar_code = self.request.query_params.get("bar_code", None)
        cate_id = self.request.query_params.get("cate_id", None)
        parent_id = self.request.query_params.get("parent_id", None)
        house_id = self.request.query_params.get("house", None)

        if goods_id:
            queryset = queryset.filter(goods_id=int(goods_id))

        if house_id:
            queryset = queryset.filter(house_id=int(house_id))

        if parent_id:
            if parent_id != "-1":
                items = Category.objects.filter(Q(path__contains=parent_id) | Q(id=int(parent_id))).values_list("id", flat=True)
                queryset = queryset.filter(goods__cate_id__in=list(items))
        elif cate_id:
            queryset = queryset.filter(goods__cate_id=int(cate_id))

        if code:
            queryset = queryset.filter(goods__code__contains=code)

        if name:
            queryset = queryset.filter(goods__name__contains=name)

        if help_code:
            queryset = queryset.filter(goods__help_code__contains=help_code)

        if bar_code:
            queryset = queryset.filter(goods__bar_code__contains=bar_code)

        return queryset

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

        self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)


class GoodsTransferDetailViewSet(ModelViewSet):
    """调拨明细"""
    permission_classes = ()
    queryset = GoodsTransferDetail.objects.all()
    serializer_class = GoodsTransferDetailSerializer
    pagination_class = None

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                self.update_goods_stock(select_ids)
                self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)

    def update_goods_stock(self, ids):
        objs = self.serializer_class.Meta.model.objects.filter(id__in=ids)
        # 减库存
        store_decrease_goods_stocks(objs)


class GoodsTransferViewSet(ModelViewSet):
    """库存调拨"""
    permission_classes = ()
    queryset = GoodsTransfer.objects.all()
    serializer_class = GoodsTransferSerializer
    pagination_class = None

    def get_queryset(self):
        queryset = super().get_queryset()

        code = self.request.query_params.get("code", None)
        search_date = self.request.query_params.getlist("search_date[]", None)
        out_house_id = self.request.query_params.get("out_house", None)
        in_house_id = self.request.query_params.get("in_house", None)
        user_id = self.request.query_params.get("user", None)

        if code:
            queryset = queryset.filter(code__contains=code)

        if search_date and len(search_date) == 2:
            queryset = queryset.filter(transfer_time__range=(search_date[0], search_date[1]))

        if out_house_id:
            queryset = queryset.filter(out_house_id_id=int(out_house_id))

        if in_house_id:
            queryset = queryset.filter(out_house_id_id=int(in_house_id))

        if user_id:
            queryset = queryset.filter(user_id=int(user_id))

        return queryset

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                store_decrease_goods_stocks(instance.details.all())
                self.perform_destroy(instance)

            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                self.update_goods_stock(select_ids)
                self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)

    def update_goods_stock(self, ids):
        transfers = self.serializer_class.Meta.model.objects.filter(id__in=ids)
        for tr in transfers:
            store_decrease_goods_stocks(tr.details.all())


class StockGoodsExportAPIView(APIView):
    """库存商品导出"""
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        house_id = request.query_params.get("house")

        queryset = GoodsStock.objects.all().order_by('goods__code')

        if house_id:
            queryset = queryset.filter(house_id=int(house_id))

        serializer = GoodsStockSerializer(queryset, many=True)

        bio = BytesIO()

        writer = pd.ExcelWriter(bio, engine='openpyxl')

        df = pd.DataFrame(serializer.data, columns=['goods_code', 'goods_name', 'goods_cate_name', 'goods_unit_name',
                                                    'house_name', 'specs', 'batch_num', 'brand', 'place', 'price',
                                                    'quantity', 'remark', 'goods_help_code'])

        df.rename(columns={'goods_code': '商品编号', 'goods_name': '商品名称', 'goods_cate_name': '商品类别',
                           'goods_unit_name': '单位', 'house_name': '所属仓库', 'specs': '规格', 'batch_num': '批号',
                           'brand': '品牌', 'place': '产地', 'price': '成本单价', 'quantity': '库存数量',
                           'remark': '备注', 'goods_help_code': '助记码'}, inplace=True)
        df.fillna("", inplace=True)
        # print(df)
        df.to_excel(writer, sheet_name='库存明细表', index=False, float_format='%.2f')

        ws = writer.book.active  # excel sheet
        # 设置行高
        align_text = Alignment(vertical='center', wrap_text=True)
        for row in range(1, ws.max_row + 1):
            ws.row_dimensions[row].height = 25
        # 设置列宽
        for col in range(1, ws.max_column + 1):
            ws.column_dimensions[get_column_letter(col)].width = 18
        # 设置边框线
        border = Border(left=Side(border_style='thin', color='000000'),
                        right=Side(border_style='thin', color='000000'),
                        top=Side(border_style='thin', color='000000'),
                        bottom=Side(border_style='thin', color='000000'))

        for row in ws.iter_rows(min_row=ws.min_row, max_row=ws.max_row, max_col=ws.max_column):
            for cell in row:
                cell.border = border
                cell.alignment = align_text
                cell.number_format = '0.00'
        writer.save()
        response = HttpResponse(bio.getvalue(), content_type="application/octet-stream")
        # bio.close()
        file_name = '商品库存明细单_{}.xlsx'.format(int(time.time()))
        response['Content-Disposition'] = "attachment;filename={}".format(escape_uri_path(file_name.encode('utf-8')))
        return response


